hysop.core.graph.computational_operator module¶
- class hysop.core.graph.computational_operator.ComputationalGraphOperator(input_fields=None, output_fields=None, **kwds)[source]¶
Bases:
ComputationalGraphNode
Interface of an abstract computational graph operator. An operator is a single graph node with its own inputs and outputs.
- For more complex operators that combines multiple operators, see
*hysop.core.graph.computational_graph.ComputationalGraph *hysop.core.graph.node_generator.ComputationalGraphNodeGenerator
- For operators that offers different implementation backend, see
*hysop.core.graph.computational_node_frontend.ComputationalGraphNodeFrontend
- About inputs and outputs fields (continuous fields):
- *An operator may be working on multiple topologies exposed by different
fields. In this case supports_multiple_topologies() should return True.
- *An continuous field may have different discretization (topologies)
as input and output. In this case supports_multiple_field_topologies() should return True.
- *An operator may support distribution along mpi processes.
In this case supports_mpi() should return True. Distribution constraints along process can be specified by redefining get_field_requirements() for inputs and outputs.
- *Min and max ghosts and input/output state (base or transposition state for exemple)
can be specified on a per variable basis in get_field_requirements()
- An operator may thus override the following class methods:
supports_multiple_topologies() supports_multiple_field_topologies() supports_mpi()
By default all those methods return False, meaning that it can only have input and output variables defined on one unique topology that is not distributed along multiple processes.
- To support the ‘method’ keyword, override the following methods:
available_methods() default_method() handle method()
- To add field contraints on variables and their topologies, override the following method:
get_field_requirements()
To set or relax global contraints on all operator variables and their topologies, override the following method:
get_operator_requirements()
To declare that an operator does not invalidate an input_field when the same field is written, override the get_preserved_input_fields method.
- An operator has to extend the following abstract method:
apply(simulation, **kwds)
- An operator may extend the definition the following methods:
pre_initialize() initialize() post_initialize() get_work_properties() setup() finalize()
When extending methods pay attention to always call base class methods first. Not calling base methods may lead to unexpected behaviours in present/future releases. When overriding methods, you can just redefine it.
See hysop.core.computational_node.ComputationalGraphNode for more information about those methods.
- Order of operation of an operator:
- __init__()
self.initialized is False self.discretized is False self.ready is False -> topologies/topology descriptors are checked
- initialize()
pre_initialize() handle method() -> self.method is set get_field_requirements() -> self.input_field_requirements it set get_operator_requirements() -> self.operator_requirements is set check_requirements_compatibility() -> updates self._initialized is set post_intialize()
check() (requires self.initialized to be set) discretize() (requires self.initialized to be set)
self.discretized is set
- get_work_properties() (requires self.discretized to be set)
returns required work (extra temporary buffers required for the computations)
- setup() (requires self.discretized to be set)
self.ready is set
- apply() (requires self.ready to be set)
abtract method to be implemented by each operator
- finalize() (requires self.ready to be set)
sets self.ready to False
Operators support checkpointing, ie. continuing a simulation state from a checkpoint stored on disk. In order for this to work, some operators may store data during checkpoint export and reload data during checkpoint import. In order for this to work, operators have to override the following methods:
checkpoint_required() should return True save_checkpoint(self, datagroup, mpi_params, io_params, compressor) load_checkpoint(self, datagroup, mpi_params, io_params, relax_constraints)
By default, datagroup are saved and retrieved based on operator name. When this is not sufficient, operators can override checkpoint_datagroup_key() to pass a custom key.
Nothing besides __init__ should be called explicitely by the user as a ComputationalGraphOperator should always be embedded into a hysop.problem.Problem, or at least, a child class of hysop.core.graph.computational_graph.ComputationalGraph.
- Parameters:
- input_discrete_fields¶
Dictionary containing continuous input fields as keys and discrete variables as values.
- Type:
- output_discrete_fields¶
Dictionary containing continuous output fields as keys and discrete variables as values.
- Type:
Notes
For the input and output fields, the keys of the dicts have to be of type
hysop.fields.continuous_field.Field
. and the values should consist ofhysop.topology.topology_descriptor.TopologyDescriptors
instances ie. an already defined topology or a topology descriptor.- The following base class variables cannot be specified in kwds
input_vars, output_vars, variables, rwork, iwork, work, backend.
Nothing besides __init__ should be called manually by the user as it should be embedded into a hysop.problem.Problem, or at least in some hysop.core.graph.computational_graph.ComputationalGraph derivative.
- classmethod available_methods()[source]¶
Returns the available methods of this node. This should return a dictionary of method as keys and possible values as a scalar or an iterable. See hysop.types.InstanceOf to support specific class types. This is used to check user method input.
- build(name=None, outputs_are_inputs=False, **kwds)[source]¶
Convert an operator to a graph and prepares it for apply.
- check()[source]¶
Check if node was correctly initialized. This calls ComputationalGraphNode.check() and then checks backend by comparing all variables topology backend to set.supported_backends().
- checkpoint_datagroup_key()[source]¶
By default the checkpoint datagroup key is based on operator name. This can be overriden to generate custom keys. Note that all keys are post-processing by using CheckpointHandler._format_zarr_key.
- checkpoint_required()[source]¶
Should return True if this operator may export/import custom checkpoint data. Can be overriden to enable operator checkpointing.
- create_topology_descriptors()[source]¶
- Called in get_field_requirements, just after handle_method
- Topology requirements (or descriptors) are:
min and max ghosts for each input and output variables
allowed splitting directions for cartesian topologies
- classmethod default_method()[source]¶
Returns the default method of this node. Default methods should be compatible with available_methods. If the user provided method dictionnaty misses some method keys, a default value for this key will be extracted from the default one.
- discretize()[source]¶
By default, an operator discretize all its variables. For each input continuous field that is also an output field, input topology may be different from the output topology.
After this call, one can access self.input_discrete_fields and self.output_discrete_fields, which contains input and output dicretised fields mapped by continuous fields.
self.discrete_fields will be a tuple containing all input and output discrete fields.
Discrete tensor fields are built back from discretized scalar fields and are accessible from self.input_tensor_fields, self.output_tensor_fields and self.discrete_tensor_fields like their scalar counterpart.
- property enable_opencl_host_buffer_mapping¶
- get_field_requirements()[source]¶
Called just after handle_method(), ie self.method has been set. Field requirements are:
required local and global transposition state, if any.
required memory ordering (either C or Fortran)
Default is Backend.HOST, no min or max ghosts, MemoryOrdering.ANY and no specific default transposition state for each input and output variables.
- get_node_requirements()[source]¶
Called after get_field_requirements to get global operator requirements.
- By default we enforce unique:
*transposition state *cartesian topology shape *memory order (either C or fortran)
Across every fields.
- get_preserved_input_fields()[source]¶
Declare fields that should not be invalidated as a set. You can only declare scalar fields that are input and output fields at the same time. For example, a redistribute operation does not invalidate input fields.
- get_work_properties()[source]¶
Returns extra memory requirements of this operator. This allows operators to request for temporary buffers that will be shared between operators in a graph to reduce the memory footprint and the number of allocations.
Returned memory is only usable during operator call (ie. in self.apply). Temporary buffers may be shared between different operators as determined by the graph builder.
By default if there is no input nor output temprary fields, this returns no requests, meanning that this node requires no extra buffers.
If temporary fields are present, their memory request are automatically computed and returned.
- handle_topologies(input_topology_states, output_topology_states)[source]¶
Called just after all topologies have been set up by the graph builder. Once this has been called, an operator can retrieve its input and output topologies contained in self.input_fields and self.output_fields.
ComputationalGraph creates the topologies we need for the current operator by using TopologyDescriptors and FieldRequirements returned by get_field_requirements().
All topologies, input and output topology states have to comply with the operator field requirements obtained with self.get_field_requirements(), else this will raise a RuntimeError because it is an internal graph builder failure.
Notes
This function will take those generated topologies and build topology view on top of it to match input and output field requirements.
Graph generated field topologies are available as values of self.input_fields and self.output_fields and are mapped by continuous Field.
In addition input_topology_states and output_topology_states are passed as argument and contain input discrete topology states and output topology states that the graph builder determined.
Once this has been checked, topologies are replaced with TopologyView instances (wich is a Topology associated to a TopologyState). A TopologyView is basically a read-only view on top of a Topology with is altered by a TopologyState.
A TopologyState is a topology dependent state, and acts as a virtual state that determines how we should perceive raw mesh data.
It may for example include a transposition state for CartesianTopology topologies, resulting in the automatic permutation of attributes when fetching attributes (global_resolution and ghosts will be transposed). It may alors contain MemoryOrdering information to tell us to see the data either as C_CONTIGUOUS or F_CONTIGUOUS.
Thus self.input_fields and self.output_fields values will containi topology state dependent topologies after this call. This allows operator implementations that are state agnostic and thus much simpler to implement without errors.
RedistributeInter may not have both input and output topology states. In that specific case, (in-|out-)topology can be None
- load_checkpoint(datagroup, mpi_params, io_params, relax_constraints)[source]¶
Reload custom operator data from a checkpoint.
Datagroup is a zarr.hierarchy.Datagroup object, see hysop.core.checkpoints.CheckpointHandler for example usage. Parameters mpi_params and io_params are MPIParams and IOParams coming from the CheckpointHandler. If relax_constraints is set, you can ignore data discreapencies such as datatype, else should an error should be raised.
Data arrays or subgroups can be accessed with the dict-like datagroup[key] syntax. Group or array metadata can be retrieved by using the group.attrs[key] or array.attrs[key] syntax where key is a string that does not contain ‘’ or ‘/’, see hysop.core.checkpoints.CheckpointHandler._format_zarr_key.
As this operation read-only, there is no need to synchronize processes. Also note that metadata type is not always the same when deserialized (for example tuples become lists).
- operators()[source]¶
Return a list containing self and IO operators that should be included into the graph. This method is called by the graph builder and should not be called by user.
- output_topology_state(output_field, input_topology_states)[source]¶
Determine a specific output discrete topology state given all input discrete topology states.
Must be redefined to help correct computational graph generation. By default, just return first input state if all input states are all the same.
If input_topology_states are different, raise a RuntimeError as default behaviour. Operators altering the state of their outputs have to override this method.
The state may include transposition state, memory order and more. see hysop.topology.transposition_state.TranspositionState for the complete list.
- save_checkpoint(datagroup, mpi_params, io_params, compressor)[source]¶
Save custom operator data to a checkpoint.
Datagroup is a zarr.hierarchy.Datagroup object, see hysop.core.checkpoints.CheckpointHandler for example usage. Parameters mpi_params and io_params are MPIParams and IOParams coming from the CheckpointHandler. You can create numpy-like arrays with datagroup.create_dataset and subgroups with datagroup.create_group. Compressor is the compressor that should be used when creating arrays with datagroup.create_dataset.
Each group or array can contain a json-serialisable dictionary of metadata. Metadata can be set as the following:
group.attrs[key] = value
- or
array.attrs[key] = value
where key is a string that does not contain ‘’ or ‘/’, see hysop.core.checkpoints.CheckpointHandler._format_zarr_key.
Only io_leader should write metadata, io_leader can be determined as (mpi_params.rank == io_params.io_leader) Multiple processes array writes should be synchronized unless they write to different blocks of data. See https://zarr.readthedocs.io/en/stable/tutorial.html#parallel-computing-and-synchronization for more information.
- setup(work)[source]¶
Setup temporary buffer that have been requested in get_work_properties(). This function may be used to execute post allocation routines. This sets self.ready flag to True. Once this flag is set one may call ComputationalGraphNode.apply() and ComputationalGraphNode.finalize().
Automatically honour temporary field memory requests.